////////////////////////////////////////////////////////////////////////
// This file is part of the simpleSID framework
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
//
// Copyright (c)Richard White, 2009
// See License.txt for a disclaimer of all warranties
// and licensing information

#include "Envelope.h"

#pragma once

class Voice
{
private:
	Envelope m_Envelope;
	Voice *m_VoiceSncSource;
	Voice *m_VoiceSncDest;
	//These are the immediate variables for our SID voice registers
	unsigned char m_byFreqLO;
	unsigned char m_byFreqHI;
	unsigned char m_byPWLO;
	unsigned char m_byPWHI;
	unsigned char m_byControl;
	
	//These variables here for ease even though they belong to envelope
	unsigned char m_byAttackDecay;
	unsigned char m_bySustainRelease;  

	//These will be the High Level View of the Voice
	unsigned short m_wFreq;
	unsigned short m_wPulseWidth;
	bool m_bNoise;
	bool m_bPulse;
	bool m_bSaw;
	bool m_bTri;
	bool m_bTest;
	bool m_bRingMod;
	bool m_bSync;
	
	//Internal Variables
	unsigned int m_dwAccumulator; //24bit really
	unsigned int m_dwShift;

	static const unsigned int m_dwMaskActiveTable[2];
	bool m_bMSBRising;
	int m_nMSBRising;
	
	int m_nMute;
public:
	Voice();
	virtual ~Voice();
	
	//These are for setting the real sid registers
	void SetFreqLO(unsigned char byFreqLO); 
	void SetFreqHI(unsigned char byFreqHI);	
	void SetPWLO(unsigned char byPWLO); //Low is a byte really
	void SetPWHI(unsigned char byPWHI); //Hi is a nibble really
	void SetControlReg(unsigned char byControlReg);
	void SetAttackDecay(unsigned char byAD);
	void SetSustainRelease(unsigned char bySR);

	void SetSyncSource(Voice *voice);
	
	//These are for setting our internal representation it just makes it easier for testing
	void SetSawWave(bool bSaw);
	void SetPulseWave(bool bPulse);
	void SetTriWave(bool bTri);
	void SetNoiseWave(bool bNoise);
	void SetTestBit(bool bTest);
	void SetRingModBit(bool bRing);
	void SetSyncBit(bool bSync);

	void SetAttack(unsigned char byAttack);
	void SetDecay(unsigned char byDecay);
	void SetSustain(unsigned char bySustain);
	void SetRelease(unsigned char byRelease);
	void SetGate(bool bGate);
	
	void SetMuteState(bool bState);
	bool GetMuteState();

	unsigned char GetFreqLO();
	unsigned char GetFreqHI();
	unsigned char GetPWLO();
	unsigned char GetPWHI();
	unsigned char GetControl();
	unsigned char GetAttackDecay();
	unsigned char GetSustainRelease();
	
	//Thse functions access the Envelope class return nibble
	unsigned char GetAttack();
	unsigned char GetDecay();
	unsigned char GetSustain();
	unsigned char GetRelease();
	
	unsigned short GetFreq();
	unsigned short GetPW();
	unsigned int GetAccumulator(); 

	bool GetNoiseOn();
	bool GetPulseOn();
	bool GetSawOn();
	bool GetTriOn();
	bool GetTestOn();
	bool GetRingModOn();
	bool GetSyncOn();

	void Reset();

	void Process();
	void Process(int iCycles);

	void Synchronize(); //This needs to be called after all the voices have been clocked
	unsigned char ReadOsc(); //8 bit register for reading voice 3
	unsigned char ReadEnvelope(); //Reads the envelope of the third voice

	int Output(); //20 bit output becuae of osc and envelope


	//Need to access Envelope functions

};
